#ifndef __CAMERA_H__
#define __CAMERA_H__

#include "osal.h"

/**
 * @brief hichannel消息结构
 * 
 */
typedef struct
{
    uint16_t msg_type;
    uint8_t  payload[0];
}hi_channel_msg_t;

/**
 * @brief msg_type定义
 * @note  WIFI --> CAMERA-HOST
 */
#define HI_MSGTYPE_SET_MAC_IP           0x0001  //设置IP和MAC payload: hi_set_mac_ip_stu_t
#define HI_MSGTYPE_START_QRCODE_SCAN    0x0002  //启动二维码扫描 payload: uint8_t(time)
#define HI_MSGTYPE_DL_FW                0x0003  //下载OTA固件 payload: hi_download_stu_t
#define HI_MSGTYPE_READ_FW              0x0004  //读取OTA固件 payload: hi_read_fw_stu_t
#define HI_MSGTYPE_LCD_CTRL             0x0005  //LCD控制 payload: hi_lcd_param_stu_t
#define HI_MSGTYPE_LCD_DIS_PICTURE      0x0006  //LCD显示图片 payload: hi_lcd_param_stu_t
#define HI_MSGTYPE_START_AV_TALK        0x0007  //启动音视频对讲 payload: hi_set_triad_info_stu_t
#define HI_MSGTYPE_START_STORAGE        0x0008  //启动音视频存储 payload: hi_start_storage_stu_t
#define HI_MSGTYPE_UPLOAD_PICTURE       0x0009  //上传图片 payload: hi_upload_picture_stu_t
#define HI_MSGTYPE_SET_HEARTBEAT_TIME   0x000A  //设置心跳超时
#define HI_MSGTYPE_AUDIO_TEST           0x000B  //语音测试（录3秒播3秒） payload: none
#define HI_MSGTYPE_SET_TIME             0x000C  //设置视频模块的时间 payload: hi_set_time_stu_t
#define HI_MSGTYPE_SET_ESN_PWD1         0x000D  //发送ESN信息到5713
#define HI_MSGTYPE_SET_FILL_LIGHT       0x000E  //开关补光灯，产测用

/**
 * @brief msg_type定义
 * @note  CAMERA-HOST --> WIFI
 */
#define HI_MSGTYPE_P2P_INFO             0x8001  //P2P信息 payload: string
#define HI_MSGTYPE_QRCODE_SCAN_REPLY    0x8002  //扫描二维码响应 payload: string
#define HI_MSGTYPE_DL_FW_REPLY          0x8003  //下载固件响应 payload: hi_download_result_enum_t
#define HI_MSGTYPE_READ_FW_REPLY        0x8004  //读固件响应 payload: hi_read_fw_stu_t
#define HI_MSGTYPE_HEARTBEAT            0x8005  //心跳 payload: none
#define HI_MSGTYPE_LCD_CLOSE            0x8006  //LCD已关闭 payload: none
#define HI_MSGTYPE_FW_VERSION           0x8007  //固件版本 payload: hi_fw_version_stu_t
#define HI_MSGTYPE_STORAGE_REPLY        0x8008  //音视频存储响应 payload: uint32_t


/**
 * @brief payload定义
 * 
 */
#pragma pack(1)
/* 固件版本 */
typedef struct
{
    char video[20];
    char uvc[20];
}hi_fw_version_stu_t;

/* 设置IP和MAC */
typedef struct
{
    uint8_t mac[6];     //MAC地址
    uint32_t ip;        //IP地址
    uint32_t gateway;   //网关
    uint32_t netmask;   //掩码
    uint32_t dns0;      //DNS0
    uint32_t dns1;      //DNS1
}hi_set_mac_ip_stu_t;

/* 固件下载结果 */
typedef enum
{
    HI_FW_DL_SUCCESS,     //固件下载成功
    HI_FW_DL_ERROR,       //固件下载失败：HTTP下载出错
    HI_FW_DL_ERROR_LEN,   //固件下载失败：长度错误，文件太大存不下
    HI_FW_DL_ERROR_STORE, //固件下载失败：存储错误，下载过程中文件存储失败
    HI_FW_DL_ERROR_MD5,   //固件MD5校验失败
    HI_FW_DL_SAME_BEFORE, //固件和上一版本相同
}hi_download_result_enum_t;

/* 固件下载参数 */
typedef struct
{
    uint8_t  devNum;    //设备编号
    uint32_t fileLen;   //固件长度
    uint8_t  md5[32+1]; //固件MD5
    uint8_t  url[0];    //下载链接
}hi_download_stu_t;

/* 读取OTA固件数据结构 */
typedef struct
{
    uint8_t devNum;       //dfu设备号（DFU_DevNum_enum_t中定义）
    uint16_t psn;         //包编号
    uint16_t len;         //包长度
    uint8_t data[0];
}hi_read_fw_stu_t;

/* 三元组信息 */
typedef struct 
{
    char productId[32];    //产品ID
    char deviceName[32];   //设备名
    char deviceSecret[32]; //设备密码
}hi_set_triad_info_stu_t;

/* 设置时间 */
typedef struct
{
    uint32_t timestamp;    //utc时间 （单位：秒）
    int32_t timezone;      //时区 （单位：秒）
}hi_set_time_stu_t;

/* 图片类型（高8位表示品牌编号，低8位表示图片类型） */
typedef enum
{
    HI_PIC_LOGO_KDS = 1<<8,  //鼎新同创logo
    HI_PIC_VIDEO_OFF_KDS,    //视频已关闭图标
    HI_PIC_LOW_POWER_KDS,    //低电量图标

    HI_PIC_LOGO_PLP = 4<<8,  //飞利浦logo
    HI_PIC_VIDEO_OFF_PLP,    //视频已关闭图标
    HI_PIC_LOW_POWER_PLP,    //低电量图标
}hi_picture_ui_enum_t;

/* 显示屏参数 */
typedef struct
{
    uint16_t pic; //图片ID （ hi_picture_ui_enum_t ）
    uint8_t time; //亮屏时长
    uint8_t bl;   //背光亮度
    uint8_t ctrl; //控制字：0取反、1点亮、2熄灭
}hi_lcd_param_stu_t;

/* 上传图片参数 */
typedef struct
{
    uint32_t timestamp; //事件时间戳
    char url[0];        //图片上传地址
}hi_upload_picture_stu_t;

/* 启动存储参数 */
typedef struct 
{
    uint32_t timestamp; //事件时间戳
    uint8_t  tc_id;     //腾讯事件ID
}hi_start_storage_stu_t;

/* 发送ESN和PWD1信息 */
typedef struct 
{
    uint8_t esn[13+1];
    uint8_t pwd1[12];
    uint8_t cert_server[200];
}hi_esn_pwd1_cert_url_t;

#pragma pack()




/**
 * @brief: 启动二维码扫描
 * 
 */
#define Camera_Start_QrcodeScan(_time)                         \
do                                                             \
{                                                              \
    uint16_t len = sizeof(hi_channel_msg_t) + sizeof(uint8_t); \
    hi_channel_msg_t *pmsg = OSAL_Malloc(len);                 \
    memset(pmsg,0,len);                                        \
    pmsg->msg_type = HI_MSGTYPE_START_QRCODE_SCAN;             \
    uint8_t *time = (uint8_t*)pmsg->payload;                   \
    *time = _time;                                             \
    OSAL_MboxPost(COMP_CAMERA, 0, pmsg, len);                  \
    OSAL_Free(pmsg);                                           \
}while (0);

/**
  * @brief  http下载文件
  * @note
  * @param  _devNum：dfu设备号
  * @param  _len：固件长度
  * @param  _md5：固件md5值
  * @param  _url：链接
  * @retval
  */
#define Camera_HttpDownload(_devNum, _len, _md5, _url)        \
do                                                            \
{                                                             \
    uint16_t len = sizeof(hi_channel_msg_t) +                 \
                   sizeof(hi_download_stu_t) +                \
                   strlen(_url) + 1;                          \
    hi_channel_msg_t *pmsg = OSAL_Malloc(len);                \
    memset(pmsg,0,len);                                       \
    pmsg->msg_type = HI_MSGTYPE_DL_FW;                        \
    hi_download_stu_t *p = (hi_download_stu_t *)pmsg->payload;\
    p->devNum = _devNum;                                      \
    p->fileLen = _len;                                        \
    strcpy(p->md5, _md5);                                     \
    strcpy(p->url, _url);                                     \
    OSAL_MboxPost(COMP_CAMERA, 0, pmsg, len);                 \
    OSAL_Free(pmsg);                                          \
} while (0);

/**
  * @brief  获取固件升级数据
  * @note
  * @param  devNum：dfu设备号（DFU_DevNum_enum_t中定义）
  * @param  psn：包编号
  * @param  len：包长度
  * @retval
  */
#define Camera_GetDfuData(_devNum, _psn, _len)                          \
do                                                                      \
{                                                                       \
    uint16_t len = sizeof(hi_channel_msg_t) + sizeof(hi_read_fw_stu_t); \
    hi_channel_msg_t *pmsg = OSAL_Malloc(len);                          \
    memset(pmsg,0,len);                                                 \
    pmsg->msg_type = HI_MSGTYPE_READ_FW;                                \
    hi_read_fw_stu_t *p = (hi_read_fw_stu_t*)pmsg->payload;             \
    p->devNum = _devNum;                                                \
    p->psn = _psn;                                                      \
    p->len = _len;                                                      \
    OSAL_MboxPost(COMP_CAMERA, 0, pmsg, len);                           \
    OSAL_Free(pmsg);                                                    \
} while (0);

/**
 * @brief LCD控制
 * 
 * @param _pic：图片编号（ hi_picture_ui_enum_t ）
 * @param _time：显示时长uint8_t（单位：s）
 * @param _bl：背光亮度uint8_t（0~100）
 * @param _ctrl：0取反LCD背光，1点亮LCD，2关闭LCD
 * 
 */
#define Camera_LcdCtrl(_pic, _time, _bl, _ctrl)                           \
do                                                                        \
{                                                                         \
    uint16_t len = sizeof(hi_channel_msg_t) + sizeof(hi_lcd_param_stu_t); \
    hi_channel_msg_t *pmsg = OSAL_Malloc(len);                            \
    memset(pmsg,0,len);                                                   \
    pmsg->msg_type = HI_MSGTYPE_LCD_CTRL;                                 \
    hi_lcd_param_stu_t *p = (hi_lcd_param_stu_t*)pmsg->payload;           \
    p->pic = (uint16_t)_pic;                                              \
    p->time = _time;                                                      \
    p->bl = _bl;                                                          \
    p->ctrl = _ctrl;                                                      \
    OSAL_MboxPost(COMP_CAMERA, 0, pmsg, len);                             \
    OSAL_Free(pmsg);                                                      \
} while (0);

/**
 * @brief 显示图片（仅显示图片UI）
 * 
 * @param _pic：图片编号（ hi_picture_ui_enum_t ）
 * @param _bl：背光亮度uint8_t（0~100）
 */
#define Camera_DisplayPicture(_pic, _bl,_time)                            \
do                                                                        \
{                                                                         \
    uint16_t len = sizeof(hi_channel_msg_t) + sizeof(hi_lcd_param_stu_t); \
    hi_channel_msg_t *pmsg = OSAL_Malloc(len);                            \
    memset(pmsg,0,len);                                                   \
    pmsg->msg_type = HI_MSGTYPE_LCD_DIS_PICTURE;                          \
    hi_lcd_param_stu_t *p = (hi_lcd_param_stu_t*)pmsg->payload;           \
    p->pic = (uint16_t)_pic;                                               \
    p->time = _time;                                                      \
    p->bl = _bl;                                                          \
    OSAL_MboxPost(COMP_CAMERA, 0, pmsg, len);                             \
    OSAL_Free(pmsg);                                                      \
} while (0);

/**
 * @brief 启动音视频存储
 * 
 * @param _timestamp：事件时间戳
 * @param _tc_id：腾讯事件ID
 * 
 */
#define Camera_StartStorage(_timestamp, _tc_id)                               \
do                                                                            \
{                                                                             \
    uint16_t len = sizeof(hi_channel_msg_t) + sizeof(hi_start_storage_stu_t); \
    hi_channel_msg_t *pmsg = OSAL_Malloc(len);                                \
    memset(pmsg,0,len);                                                       \
    pmsg->msg_type = HI_MSGTYPE_START_STORAGE;                                \
    hi_start_storage_stu_t *p = (hi_start_storage_stu_t*)pmsg->payload;       \
    p->timestamp = _timestamp;                                                \
    p->tc_id = _tc_id;                                                     \
    OSAL_MboxPost(COMP_CAMERA, 0, pmsg, len);                                 \
    OSAL_Free(pmsg);                                                          \
} while (0);

/**
 * @brief 启动音视频对讲
 * 
 * @param 三个参数都要传字符串
 * 
 */
#define Camera_StartAvTalk(_productId, _deviceName, _deviceSecret)             \
do                                                                             \
{                                                                              \
    uint16_t len = sizeof(hi_channel_msg_t) + sizeof(hi_set_triad_info_stu_t); \
    hi_channel_msg_t *pmsg = OSAL_Malloc(len);                                 \
    memset(pmsg,0,len);                                                        \
    pmsg->msg_type = HI_MSGTYPE_START_AV_TALK;                                 \
    hi_set_triad_info_stu_t *p = (hi_set_triad_info_stu_t*)pmsg->payload;      \
    strcpy(p->productId, _productId);                                          \
    strcpy(p->deviceName, _deviceName);                                        \
    strcpy(p->deviceSecret, _deviceSecret);                                    \
    OSAL_MboxPost(COMP_CAMERA, 0, pmsg, len);                                  \
    OSAL_Free(pmsg);                                                           \
} while (0);

/**
 * @brief 设置视频模块的时间
 * 
 */
#define Camera_SetTime(_timestamp, _zone)                                \
do                                                                       \
{                                                                        \
    uint16_t len = sizeof(hi_channel_msg_t) + sizeof(hi_set_time_stu_t); \
    hi_channel_msg_t *pmsg = OSAL_Malloc(len);                           \
    memset(pmsg,0,len);                                                  \
    pmsg->msg_type = HI_MSGTYPE_SET_TIME;                                \
    hi_set_time_stu_t *p = (hi_set_time_stu_t*)pmsg->payload;            \
    p->timestamp = _timestamp;                                           \
    p->timezone = _zone;                                                 \
    OSAL_MboxPost(COMP_CAMERA, 0, pmsg, len);                            \
    OSAL_Free(pmsg);                                                     \
} while (0);

/**
 * @brief 上传图片
 * 
 * @param _timestamp：事件时间戳uint32_t
 * @param _url：图片上传路径string
 * 
 */
#define Camera_UploadPicture(_timestamp, _url)                           \
do                                                                       \
{                                                                        \
    uint16_t len = sizeof(hi_channel_msg_t) +                            \
                   sizeof(hi_upload_picture_stu_t) +                     \
                   strlen(_url) + 1;                                     \
    hi_channel_msg_t *pmsg = OSAL_Malloc(len);                           \
    memset(pmsg,0,len);                                                  \
    pmsg->msg_type = HI_MSGTYPE_UPLOAD_PICTURE;                          \
    hi_upload_picture_stu_t *p = (hi_upload_picture_stu_t*)pmsg->payload;\
    p->timestamp = _timestamp;                                           \
    strcpy(p->url, _url);                                                \
    OSAL_MboxPost(COMP_CAMERA, 0, pmsg, len);                            \
    OSAL_Free(pmsg);                                                     \
} while (0);

/**
 * @brief 设置心跳超时，用于5713-OTA时用
 * 
 * @param _timeout:心跳超时（单位：秒uint8_t ）
 * 
 */
#define Camera_SetHeartTime(_timeout)                                    \
do                                                                       \
{                                                                        \
    uint16_t len = sizeof(hi_channel_msg_t) +  sizeof(uint8_t);          \
    hi_channel_msg_t *pmsg = OSAL_Malloc(len);                           \
    memset(pmsg,0,len);                                                  \
    pmsg->msg_type = HI_MSGTYPE_SET_HEARTBEAT_TIME;                      \
    uint8_t *p = (uint8_t*)pmsg->payload;                                \
    *p = _timeout;                                                       \
    OSAL_MboxPost(COMP_CAMERA, 0, pmsg, len);                            \
    OSAL_Free(pmsg);                                                     \
} while (0);

/**
 * @brief 语音模块测试（产测会用到）
 * 
 * @note  录3秒播3秒
 * 
 */
#define Camera_AudioTest()                            \
do                                                    \
{                                                     \
    hi_channel_msg_t msg;                             \
    msg.msg_type = HI_MSGTYPE_AUDIO_TEST;             \
    OSAL_MboxPost(COMP_CAMERA, 0, &msg, sizeof(msg)); \
} while (0);

/**
 * @brief 发送ESN和PWD1（下载根证书需要用）
 * 
 * @note  
 * @param esn
 * 
 */
#define Camera_SetEsn_Pwd1(cert_param)                                          \
do                                                                              \
{                                                                               \
    uint16_t len = sizeof(hi_channel_msg_t) +  sizeof(hi_esn_pwd1_cert_url_t);  \
    hi_channel_msg_t *pmsg = OSAL_Malloc(len);                                  \
    memset(pmsg,0,len);                                                         \
    pmsg->msg_type = HI_MSGTYPE_SET_ESN_PWD1;                                   \
    memcpy(pmsg->payload,cert_param,sizeof(hi_esn_pwd1_cert_url_t));            \                                      
    OSAL_MboxPost(COMP_CAMERA, 0, pmsg, len);                                   \
    OSAL_Free(pmsg);                                                            \
} while (0);

/**
 * @brief 开关补光灯用
 * 
 * @note  产测时用
 * @param onoff 1：开；0：关
 * 
 */
#define Camera_SetFillLight(onoff)                                       \
do                                                                       \
{                                                                        \
    uint16_t len = sizeof(hi_channel_msg_t) +  sizeof(uint8_t);          \
    hi_channel_msg_t *pmsg = OSAL_Malloc(len);                           \
    memset(pmsg,0,len);                                                  \
    pmsg->msg_type = HI_MSGTYPE_SET_FILL_LIGHT;                          \
    *(pmsg->payload) = onoff;                                            \
    OSAL_MboxPost(COMP_CAMERA, 0, pmsg, len);                            \
    OSAL_Free(pmsg);                                                     \
} while (0);

#endif /* __CAMERA_H__ */
